/* 
  Copyright (c) SilverLining 2015
  Date:    2016-1-7
  File:    Message.cpp  
  Description: 

*/

#include "stdafx.h"

using namespace System;
using namespace System::Security;
using namespace System::Threading;
using namespace System::Runtime::Serialization;
using namespace System::Collections::Generic;

#include "shim_object.h"
#include "shim_process.h"
#include "shim_data.h"
#include "BadResultException.h"
#include "Package.h"
#include "Archiver.h"
#include "GameObject.h"
#include "TimerState.h"
#include "Package.h"
#include "Game.h"
#include "MessageType.h"
#include "Message.h"
#include "Process.h"

using namespace m;

namespace SL
{
	namespace M
	{
		Message::Message(m::message* message)
			: _Sender(nullptr),
			_data(nullptr),
			_msg(nullptr)
		{
			assert(message);
			if (message)
			{
				_msg = message;
				message->reference();

				ref_storage track1;
				shim_process* sender = lock<shim_process>(track1, message->sender());
				if (sender)
				{
					_Sender = sender->get_process();
				}

				if (message->data())
				{
					shim_data* data = dynamic_cast<shim_data*>(message->data());
					if (data)
					{
						_data = data->Obj;
					}
					else
					{
						shim_process* proc = dynamic_cast<shim_process*>(message->data());
						if (proc)
						{
							_data = proc->get_process();
						}
						else
						{
							shim_object* obj = dynamic_cast<shim_object*>(message->data());
							if (obj)
							{
								_data = obj->get_object();
							}
						}
					}
				}
			}
		}

		Message::~Message()
		{
			Message::!Message();
		}

		Message::!Message()
		{
			if (_msg)
			{
				_msg->release();
			}
		}

		Process^ Message::Sender::get()
		{
			return _Sender;
		}

		MessageType^ Message::TypeId::get()
		{
			return MessageType::Get(gcnew String(_msg->type()));
		}

		m::message* Message::NativePtr::get()
		{
			return _msg;
		}

		System::Object^ Message::Data::get()
		{
			return _data;
		}

		System::String ^ Message::ToString()
		{
			return String::Format(System::Globalization::CultureInfo::InvariantCulture, "{0} {{ Sender: {1}, Type: {2}, Message: {3} }}", this->GetType()->ToString(), Sender, TypeId, Data);
		}

		bool Message::TypeEquals(MessageType ^ messageType)
		{
			pin_ptr<const wchar_t> typeChars = PtrToStringChars(messageType->_type);
			return _msg->type_equals(typeChars);
		}
	}
}